package sanshui.system.trade.service;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import sanshui.system.trade.common.CommonResponse;
import sanshui.system.trade.common.GlobalContain;
import sanshui.system.trade.common.TradeType;
import sanshui.system.trade.db.entity.*;
import sanshui.system.trade.db.mapper.*;
import sanshui.system.trade.factory.data.DataLevelKey;
import sanshui.system.trade.factory.data.DataMarketType;
import sanshui.system.trade.factory.operate.OperateStatus;
import sanshui.system.trade.factory.trade.position.PositionCanTradeVo;
import sanshui.system.trade.factory.trade.position.StockPositionStatus;
import sanshui.system.trade.factory.trade.position.StockPositionType;
import sanshui.system.trade.factory.trade.strategy.StrategyCallType;
import sanshui.system.trade.model.TradeAccountModel;
import sanshui.system.trade.model.TradeHisPositionModel;
import sanshui.system.trade.model.TradeWorkerModel;
import sanshui.system.trade.pojo.StockInfoVo;
import sanshui.system.trade.pojo.ao.CreateAccountAo;
import sanshui.system.trade.pojo.ao.GetStrategyResultInfoAo;
import sanshui.system.trade.pojo.ao.QueryAccAo;
import sanshui.system.trade.util.CommonTimeUtil;
import sanshui.system.trade.util.IdWorkerUtil;
import sanshui.system.trade.util.TradePositionUtil;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
@Slf4j
public class AccountServiceImpl implements IAccountService {
    @Resource
    IdWorkerUtil idWorkerUtil;
    @Resource
    TradeAccountMapper accountMapper;
    @Resource
    TradeWorkerMapper tradeWorkerMapper;

    @Override
    public TradeAccountModel createAccount(TradeWorkerModel tradeWorkerModel) {
        TradeAccountModel tradeAccount = new TradeAccountModel();
        tradeAccount.setUserId(1995L);
        tradeAccount.setAccDesc(tradeWorkerModel.getAccDesc());
        tradeAccount.setInitValue(Long.parseLong(tradeWorkerModel.getInitValue()) * 100L);
        tradeAccount.setCurrentCash(Long.parseLong(tradeWorkerModel.getInitValue()) * 100L);
        tradeAccount.setCurrentValue(0L);
        tradeAccount.setAccStatus(TradeType.AccountStatus.IN.getIndex());
        tradeAccount.setDelFlg(TradeType.DelFlg.EXIT.getCode());
        tradeAccount.setStartDatetime(tradeWorkerModel.getStartTime());
        tradeAccount.setEndDatetime(tradeWorkerModel.getEndTime());
        tradeAccount.setMarketType(tradeWorkerModel.getTradeMarketKey());
        tradeAccount.setBuyFeeRateGuo(Integer.parseInt(tradeWorkerModel.getBuyFeeRateGuo()));
        tradeAccount.setBuyFeeRateQuan(Integer.parseInt(tradeWorkerModel.getBuyFeeRateQuan()));
        tradeAccount.setSellFeeRateGuo(Integer.parseInt(tradeWorkerModel.getSellFeeRateGuo()));
        tradeAccount.setSellFeeRateQuan(Integer.parseInt(tradeWorkerModel.getSellFeeRateQuan()));
        tradeAccount.setSellFeeRateYin(Integer.parseInt(tradeWorkerModel.getSellFeeRateYin()));
        tradeAccount.setSellFixedFee(Integer.parseInt(tradeWorkerModel.getSellFixedFee()));
        tradeAccount.setBuyFixedFee(Integer.parseInt(tradeWorkerModel.getBuyFixedFee()));
        tradeAccount.setFeeAround(100);
        tradeAccount.setFeeRateAround(1000000);
        tradeAccount.setAccountType(tradeWorkerModel.getTradeSystemType());
        int insert = accountMapper.insert(tradeAccount);
        tradeAccount.setAccId(idWorkerUtil.nowId(IdWorkerUtil.IdType.ACCOUNT_ID));
        if(insert > 0){
            TradeWorker tradeWorker = new TradeWorker();
            tradeWorker.setUserId(tradeAccount.getUserId());
            tradeWorker.setAccId(tradeAccount.getAccId());
            tradeWorker.setTradeMarketKey(tradeAccount.getMarketType());
            tradeWorker.setTradeFrequent(tradeWorkerModel.getFrequency());
            tradeWorker.setTradeSystemType(tradeWorkerModel.getTradeSystemType());
            tradeWorker.setDataMarketType(tradeWorkerModel.getDataMarketType());
            tradeWorker.setFilterRule(JSONObject.toJSONString(tradeWorkerModel.getFilterModel()));

            tradeWorker.setWorkerDesc(tradeWorkerModel.getTradeName());
            tradeWorker.setIndicatorCodes(Strings.join(tradeWorkerModel.getIndicators(), ','));
            tradeWorker.setTargetIndex(Strings.join(tradeWorkerModel.getChooseTargetsIndex(), ','));
            tradeWorker.setTargetCodes(Strings.join(tradeWorkerModel.getChooseTargets(), ','));
            tradeWorker.setStrategyCode(tradeWorkerModel.getStrategy());
            tradeWorker.setUpdateTime(CommonTimeUtil.getNowTime16());
            tradeWorker.setWorkerStatus(TradeType.WorkerStatus.END.getCode());
            tradeWorker.setDelFlg(TradeType.DelFlg.EXIT.getCode());
            tradeWorker.setStartTime(tradeWorkerModel.getStartTime());
            tradeWorker.setEndTime(tradeWorkerModel.getEndTime());
            tradeWorkerMapper.insert(tradeWorker);
            tradeWorkerModel.setWorkerId(idWorkerUtil.nowId(IdWorkerUtil.IdType.WORKER_ID));
            return tradeAccount;
        }
        return null;
    }

    @Override
    public List<TradeAccount> findAccount(QueryAccAo queryAccAo) {
        TradeAccountExample ex = new TradeAccountExample();
        TradeAccountExample.Criteria criteria = ex.createCriteria();
        if (Strings.isNotEmpty(queryAccAo.getAccountType())){
            criteria.andAccountTypeEqualTo(queryAccAo.getAccountType());
        }
        if (Strings.isNotEmpty(queryAccAo.getAccId())){
            criteria.andAccIdEqualTo(Long.parseLong(queryAccAo.getAccId()));
        }
        criteria.andDelFlgEqualTo(TradeType.DelFlg.EXIT.getCode());
        return accountMapper.selectByExample(ex);
    }

    @Override
    public TradeHisOpPos buildOpPos(Long accId, Long workerId, Long price, Long num, Long fee, String code, StrategyCallType operationType, String datetime16) {
        TradeHisOpPos tradeHisOpPos = new TradeHisOpPos();
        tradeHisOpPos.setAccId(accId);
        tradeHisOpPos.setWorkerId(workerId);
        tradeHisOpPos.setOpType(operationType.name());
        tradeHisOpPos.setTargetCode(code);
        tradeHisOpPos.setTradePrice(price);
        tradeHisOpPos.setTradeNum(num);
        tradeHisOpPos.setOpTime(datetime16);
        return tradeHisOpPos;
    }

    @Override
    public int updateAccStatus(Long accId, int newStatus, int oldStatus) {
        TradeAccount tradeAccount = new TradeAccount();
        tradeAccount.setAccId(accId);
        tradeAccount.setAccStatus(newStatus);
        return accountMapper.updateByPrimaryKeySelective(tradeAccount);
    }

    @Override
    public int updateAccByAccId(Long accId, TradeAccount tradeAccount) {
        tradeAccount.setAccId(accId);
        return accountMapper.updateByPrimaryKeySelective(tradeAccount);
    }

    @Override
    public void deleteAccWorker(Long workerId) {
        TradeWorker tradeWorker = new TradeWorker();
        tradeWorker.setWorkerId(workerId);
        tradeWorker.setWorkerStatus(TradeType.WorkerStatus.END.getCode());
        tradeWorker.setDelFlg(TradeType.DelFlg.DELETE.getCode());
        tradeWorkerMapper.updateByPrimaryKeySelective(tradeWorker);
    }
}